#include "HDFTest.h"

HDF::HDF(const char *fileName)
:FILE_NAME(fileName)
{
	try
	{
		/*Exception::dontPrint();*/

		file=new H5File( FILE_NAME, H5F_ACC_TRUNC);
	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}
}

HDF::~HDF()
{
	delete file;
}
void HDF::write(int *data, int size, const char* datasetName)
{
	try
	{
		Exception::dontPrint();

		hsize_t sizet[1];
		hsize_t offset[1];
		hsize_t dims[1];
		DataSet dataset;
		DataSpace filespace;

		if (!isDataSetExist(datasetName))
		{
			//hsize_t dims[1];
			createNewDataSet(size,datasetName,Int);

			dataset=file->openDataSet(datasetName);
			sizet[0]=size;
			dataset.extend(sizet);

			filespace = dataset.getSpace();
			offset[0] = 0;

			dims[0] = size;            /* data dimensions */
			filespace.selectHyperslab(H5S_SELECT_SET,dims,offset);
			

			dataset.write(data,PredType::NATIVE_INT,dataset.getSpace(),filespace);
			dataset.close();
		}
		else
		{
			dataset=file->openDataSet(datasetName);

			IntType intype=dataset.getIntType();
			sizet[0]   = intype.getSize()+1+size;
			dataset.extend( sizet );

			filespace = dataset.getSpace ();
			offset[0] = intype.getSize()+1;

			dims[0]=size;
			filespace.selectHyperslab( H5S_SELECT_SET, dims, offset );

			DataSpace mspace(1,dims);
			dataset.write(data,PredType::NATIVE_INT,mspace,filespace);
			dataset.close();
		}

	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSet operations
	catch( DataSetIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataSpaceIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataTypeIException error )
	{
		error.printError();
	}
}

void HDF::write(char **data, int size, const char* datasetName)
{
	try
	{
		Exception::dontPrint();

		hsize_t sizet[1];
		hsize_t offset[1];
		hsize_t dims[1];
		DataSet dataset;
		DataSpace filespace;

		if (!isDataSetExist(datasetName))
		{
			hsize_t dims[1];
			createNewDataSet(size,datasetName,Str);

			dataset=file->openDataSet(datasetName);
			sizet[0]=size;
			dataset.extend(sizet);

			filespace = dataset.getSpace();
			offset[0] = 0;

			dims[0] = size;            /* data dimensions */
			filespace.selectHyperslab(H5S_SELECT_SET,dims,offset);

			dataset.write(data,dataset.getDataType());
			dataset.close();
		}
		else
		{
			dataset=file->openDataSet(datasetName);

			StrType strtype=dataset.getStrType();
			sizet[0]   = strtype.getSize()+1+size;
			dataset.extend( sizet );

			filespace = dataset.getSpace ();
			offset[0] = strtype.getSize()+1;

			dims[0]=size;
			filespace.selectHyperslab( H5S_SELECT_SET, dims, offset );

			DataSpace mspace(1,dims);
			dataset.write(data,dataset.getDataType(),mspace,filespace);
			dataset.close();
		}

	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSet operations
	catch( DataSetIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataSpaceIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataTypeIException error )
	{
		error.printError();
	}
}

bool HDF::isDataSetExist(const char* datasetName)
{

	try
	{
		file->openDataSet(datasetName);
	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		return false;
	}
	return true;
}

void HDF::createNewDataSet(hsize_t* dims,hsize_t* maxdims, hsize_t* chunk_dims, const char* datasetName, dataType dtype)
{
	try
	{
		Exception::dontPrint();

		//hsize_t dims[1];
		//hsize_t maxdims[1];
		//dims[0]=size;
		//maxdims[0]=H5S_UNLIMITED;
		DataSpace dataspace(1,dims,maxdims);

		DSetCreatPropList cparms;
		//hsize_t chunk_dims[1]={size};
		cparms.setChunk(1,chunk_dims);

		//int fill_val = 0;
		//cparms.setFillValue( dataType, &fill_val);

		switch (dtype)
		{
		case 0:
			{
				file->createDataSet(datasetName,PredType::NATIVE_INT,dataspace,cparms);
				break;
			}

		case 1:
			{
				StrType strType(0,H5T_VARIABLE);
				file->createDataSet(datasetName,strType,dataspace,cparms);
				break;
			}

		default:
			break;
		}
		//file->createDataSet(datasetName,dataType,dataspace,cparms);
	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSet operations
	catch( DataSetIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataSpaceIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataTypeIException error )
	{
		error.printError();
	}
}
void HDF::createNewDataSet(int size, const char* datasetName, dataType dtype)
{
	try
	{
		Exception::dontPrint();

		hsize_t dims[1];
		hsize_t maxdims[1];
		dims[0]=size;
		maxdims[0]=H5S_UNLIMITED;
		DataSpace dataspace(1,dims,maxdims);

		DSetCreatPropList cparms;
		hsize_t chunk_dims[1]={size};
		cparms.setChunk(1,chunk_dims);

		//int fill_val = 0;
		//cparms.setFillValue( dataType, &fill_val);

		switch (dtype)
		{
		case 0:
			{
				file->createDataSet(datasetName,PredType::NATIVE_INT,dataspace,cparms);
				break;
			}

		case 1:
			{
				StrType strType(0,H5T_VARIABLE);
				file->createDataSet(datasetName,strType,dataspace,cparms);
				break;
			}

		default:
			break;
		}
		//file->createDataSet(datasetName,dataType,dataspace,cparms);
	}
	// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSet operations
	catch( DataSetIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataSpaceIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataTypeIException error )
	{
		error.printError();
	}
}

void HDF::read(void *data, const char *datasetName)
{
	try
	{
		Exception::dontPrint();
		DataSet dataset=file->openDataSet(datasetName);

		dataset.read(data,dataset.getDataType());
	}
		// catch failure caused by the H5File operations
	catch( FileIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSet operations
	catch( DataSetIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataSpaceIException error )
	{
		error.printError();
	}

	// catch failure caused by the DataSpace operations
	catch( DataTypeIException error )
	{
		error.printError();
	}

}